import { watch } from 'rollup';
import Dep from './observe/dep';
import { observe } from './observe/index';
import Watch, { nextTick } from './observe/watcher';
export function initState(vm) {
  const opts = vm.$options;
  if (opts.data) { //用户有传data
    initData(vm); //初始化data
  }
  if (opts.computed) {
    initComputed(vm);
  }
  if (opts.watch) {
    initWatch(vm);
  }
}
function initWatch(vm) {
  let watch = vm.$options.watch
  for (let key in watch) {
    const handler = watch[key];
    if (Array.isArray(handler)) {
      for (let i = 0; i < handler.length; i++) {
        createWatcher(vm, key, handler[i])
      }
    } else {
      createWatcher(vm, key, handler)
    }
  }
}
function createWatcher(vm, key, handler) {
  if (typeof handler === "string") {
    handler = vm[handler];
  }
  return vm.$watch(key, handler);
}
// 作用代理：vm._data.name --> vm.name 具体函数
function Proxy(vm, target, key) {
  Object.defineProperty(vm, key, {
    get() {
      return vm[target][key];
    },
    set(newValue) {
      return vm[target][key] = newValue;
    }
  })
}
function initData(vm) {
  let data = vm.$options.data; //获取用户对象配置，data可能是函数或对象
  data = typeof data === 'function' ? data.call(vm) : data;
  vm._data = data;
  //对数据进行劫持 vue2 里采用了一个api defineProperty
  observe(data);
  // 作用代理：vm._data.name --> vm.name  
  // 代理其实也是使用defineProperty进行属性的重写
  for (let key in data) { //key是 健 例如：name
    Proxy(vm, "_data", key);
  }
}
function initComputed(vm) {
  const computed = vm.$options.computed;
  const watchers = vm._computedWatchers = {}
  for (let key in computed) {
    const userDef = computed[key]
    let fn = typeof userDef === 'function' ? userDef : userDef.get;
    watchers[key] = new Watch(vm, fn, { lazy: true }) // {lazy:true}代表懒执行,不要一加载就立马执行
    defineComputed(vm, key, userDef)
  }
}
function defineComputed(target, key, userDef) {
  const getter = typeof userDef === 'function' ? userDef : userDef.get;
  const setter = userDef.set || (() => { })
  Object.defineProperty(target, key, {
    get: createComputedGetter(key),
    set: setter
  })
}
function createComputedGetter(key) { //缓存
  return function () {
    const watcher = this._computedWatchers[key];
    if (watcher.dirty) {
      watcher.evaluate();
    }
    if (Dep.target) {
      watcher.depend();
    }
    return watcher.value;
  }
}
export function initStateMixin(Vue) {
  //异步更新状态
  Vue.prototype.$nextTick = nextTick;
  //监控文件的状态
  Vue.prototype.$watch = function (exprOrFn, cb, options = {}) {
    new watch(this, exprOrFn, { user: true }, cb);
  }

}
